import { Module, ClassSerializerInterceptor } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import { TypeOrmModule } from "@nestjs/typeorm";
import { ScheduleModule } from "@nestjs/schedule";
import { ServeStaticModule } from "@nestjs/serve-static";
import type { RedisClientOptions } from "redis";
import { redisStore } from "cache-manager-redis-yet";
import { CacheModule } from "@nestjs/cache-manager";
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR } from "@nestjs/core";
import { EventEmitterModule } from "@nestjs/event-emitter";
import { join } from "node:path";

import { UserModule } from "./user/user.module";
import { AuthModule } from "./auth/auth.module";
import { FieldConfig, ValidationSchema, envConfig, ormConfig } from "./config";
import { SocketModule } from "./socket/socket.module";
import { DeviceModule } from "./device/device.module";
import { FileModule } from "./file/file.module";
import { ResponseTransformInterceptor } from "./FGIP/intercept/response.transform.intercept";
import { JwtModule } from "./jwt/jwt.module";
import { JwtGuard } from "./FGIP/guard/jwt.guard";
import { AnyExceptionFilter } from "./FGIP/filter/any-exception.filter";
import { RolesGuard } from "./FGIP/guard/role.guard";
import { RoleModule } from "./role/role.module";
import { StoreModule } from "./store/store.module";

@Module({
    imports: [
        ConfigModule.forRoot({
            isGlobal: true,
            load: [() => envConfig, () => FieldConfig],
            validationSchema: ValidationSchema,
        }),
        StoreModule.forRoot(),
        CacheModule.registerAsync<RedisClientOptions>({
            isGlobal: true,
            imports: [ConfigModule],
            inject: [ConfigService],
            useFactory: async (configservice: ConfigService) => ({
                store: await redisStore({
                    ttl: configservice.get("CACHE_TTL"),
                    url: `redis://${configservice.get("REDIS_HOST")}:${configservice.get("REDIS_PORT")}`,
                    password: configservice.get("REDIS_PASSWORD"),
                }),
            }),
        }),
        EventEmitterModule.forRoot({
            global: true,
        }),
        TypeOrmModule.forRoot(ormConfig),
        ScheduleModule.forRoot(),
        ServeStaticModule.forRoot({
            rootPath: join(__dirname, "..", "public"),
        }),
        JwtModule,
        RoleModule,
        UserModule,
        AuthModule,
        SocketModule,
        DeviceModule,
        FileModule,
    ],
    providers: [
        {
            provide: APP_FILTER,
            useClass: AnyExceptionFilter,
        },
        {
            provide: APP_INTERCEPTOR,
            useClass: ClassSerializerInterceptor,
        },
        {
            provide: APP_INTERCEPTOR,
            useClass: ResponseTransformInterceptor,
        },
        {
            provide: APP_GUARD,
            useClass: JwtGuard,
        },
        {
            provide: APP_GUARD,
            useClass: RolesGuard,
        },
    ],
})
export class AppModule {}
